/******************************************************************************
 * Copyright (C) 2010 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.template;

import java.io.File;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.log.NullLogChute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.code.common.exception.UtilException;
import com.code.common.systeminit.EnviromentInfo;
import com.code.common.util.JsonUtil;

/**
 * Velocity模板引擎
 * 
 * @author 郑重
 * @since 1.0
 * @version 2011-2-18 郑重
 */
public class VelocityTemplate {
    
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(VelocityTemplate.class);
    
    /**
     * 模板路径
     */
    private List<String> templatePath = new ArrayList<String>(10);
    
    /**
     * @return 获取 templatePath属性值
     */
    public List<String> getTemplatePath() {
        return templatePath;
    }
    
    /**
     * @param templatePath 设置 templatePath 属性值为参数值 templatePath
     */
    public void setTemplatePath(List<String> templatePath) {
        this.templatePath = templatePath;
    }
    
    /**
     * 初始化
     */
    public void init() {
        Properties objProperties = new Properties();
        // 设置模板的路径
        objProperties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, getTemplatePathString());
        objProperties.setProperty(Velocity.FILE_RESOURCE_LOADER_CACHE, "true");
        objProperties.setProperty(Velocity.COUNTER_NAME, "index");
        objProperties.setProperty(Velocity.COUNTER_INITIAL_VALUE, "0");
        objProperties.setProperty(Velocity.INPUT_ENCODING, "GBK");
        objProperties.setProperty(Velocity.OUTPUT_ENCODING, "GBK");
        Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, new NullLogChute());
        try {
            Velocity.init(objProperties);
        } catch (Exception e) {
            LOGGER.error("Velocity模板引擎初始化失败", e);
            //throw new UtilException("Velocity模板引擎初始化失败", e);
        }
    }
    
    /**
     * 返回模板路径字符串
     * 
     * @return 模板路径字符串用逗号分隔
     */
    private String getTemplatePathString() {
        StringBuffer sbResult = new StringBuffer(256);
        String strRootPath = EnviromentInfo.getWebInfPath();
        for (String strPath : templatePath) {
            String strTemplatePath = strRootPath + strPath;
            File objTemplateDirectory = new File(strTemplatePath);
            if (!objTemplateDirectory.exists()) {
                LOGGER.error("模版文件目录{}不存在,请确认配置是否正确", strTemplatePath);
                continue;
            }
            sbResult.append(strTemplatePath).append(",");
            List<String> lstSubDirectorys = scanPath(objTemplateDirectory);
            for (String strDirectory : lstSubDirectorys) {
                sbResult.append(strDirectory).append(",");
            }
        }
        return sbResult.toString();
    }
    
    /**
     * 扫描目录
     * 
     * @param rootPath 根路径
     * @return 目录列表
     */
    private List<String> scanPath(File rootPath) {
        List<String> lstPaths = new ArrayList<String>();
        File[] objDirectorys = rootPath.listFiles();
        for (File objFile : objDirectorys) {
            if (objFile.isDirectory()) {
                lstPaths.add(objFile.getPath());
                lstPaths.addAll(scanPath(objFile));
            }
        }
        return lstPaths;
    }
    
    /**
     * 获取模板
     * 
     * @param name 模板名称
     * @return 模板
     */
    private Template getTemplate(String name) {
        Template objResult = null;
        try {
            objResult = Velocity.getTemplate(name);
        } catch (Exception e) {
            LOGGER.error("获取Velocity模板失败：" + name, e);
            //throw new UtilException("获取Velocity模板失败：" + name, e);
        }
        return objResult;
    }
    
    /**
     * 获取模板
     * 
     * @param name 模板名称
     * @param encoding 编码
     * @return 模板
     */
    private Template getTemplate(String name, String encoding) {
        Template objResult = null;
        try {
            objResult = Velocity.getTemplate(name, encoding);
        } catch (Exception e) {
            LOGGER.error("获取Velocity模板失败 name：" + name + " encoding:" + encoding, e);
            //throw new UtilException("获取Velocity模板失败 name：" + name + " encoding:" + encoding, e);
        }
        return objResult;
    }
    
    /**
     * 获取模板
     * 
     * @param content 内容map
     * @param writer Writer
     * @param name 模板名称
     * @param encoding 编码
     */
    public void merge(Map<String, Object> content, Writer writer, String name, String encoding) {
        try {
            Template objTemplate = this.getTemplate(name, encoding);
            VelocityContext objContext = new VelocityContext(content);
            objContext.put("null", NullTool.getInstance());
            objContext.put("JsonUtil", JsonUtil.getInstance());
            objTemplate.merge(objContext, writer);
        } catch (Exception e) {
            LOGGER.error("解析模板失败 name:" + name + " content:" + content + " encoding:" + encoding, e);
           // throw new UtilException("解析模板失败 name:" + name + " content:" + content + " encoding:" + encoding, e);
        }
    }
    
    /**
     * 解析模板
     * 
     * @param content 内容map
     * @param writer Writer
     * @param name 模板名称
     */
    public void merge(Map<String, Object> content, Writer writer, String name) {
        try {
            Template objTemplate = this.getTemplate(name);
            VelocityContext objContext = new VelocityContext(content);
            objContext.put("null", NullTool.getInstance());
            objContext.put("JsonUtil", JsonUtil.getInstance());
            objTemplate.merge(objContext, writer);
        } catch (Exception e) {
            LOGGER.error("解析模板失败 name:" + name + " content:" + content, e);
            //throw new UtilException("解析模板失败 name:" + name + " content:" + content, e);
        }
    }
}